package es.unileon.rnag.jgen.genes;

/**
 * Clase que representa un gen que toma valores num&eacute;ricos dentro de un rango. Implementa Gen<Double>
 * @author Abel Mayorga Gonz&aacute;lez
 * @author Sergio Fern&aacute;ndez Mart&iacute;nez
 * @version 1.0
 */
public class GenRango implements Gen<Double> {

	private double _minimo;
	private double _maximo;
	private double _precision;
	
	private long _valor;
	
	/**
	 * Constructor. El gen toma un valor escogido aleatoriamente entre los posibles.
	 * @param min: L&iacute;mite inferior del rango. El rango incluye este valor
	 * @param max: L&iacute;mite superior del rango. El rango excluye este valor
	 * @param precision: Precisi&oacute;n de los datos del rango.
	 */
	public GenRango(double min, double max, double precision){
		_minimo = min;
		_maximo = max;
		_precision = precision;
		
		_valor = (long)Math.floor(Math.random()*((_maximo-_minimo)/precision));
	}
	
	@Override
	public Double getValor() {
		return _valor*_precision+_minimo;
	}

	@Override
	public boolean esValido(Double valor) {
		return (_minimo <= valor) && (_maximo > valor);
	}


	@Override
	public String getBitString() {
		int bits = (int)Math.ceil(Math.log((_maximo-_minimo)/_precision)/Math.log(2));
		String bitString = Long.toBinaryString(_valor);
		while(bitString.length()<bits){
			bitString = "0".concat(bitString);
		}
		return bitString;
	}

	@Override
	public boolean asignarValor(String bits) {
		return asignarValor(Long.parseLong(bits, 2)*_precision);
	}

	@Override
	public boolean asignarValor(Double valor) {
		if(esValido(valor)){
			this._valor = (long)Math.floor(valor/_precision);
			return true; 
		} else {
			return false;
		}
	}

	@Override
	public Gen<Double> clonar() {
		GenRango clon = new GenRango(_minimo,_maximo,_precision);
		clon.asignarValor(_valor*_precision);
		return clon;
	}

}
